/*
*    Phantom v2.0 GUI Automation Software
*    Copyright (C) 2009  John C. Van Arsdall (john@phantomtest.com)
*
*    This program is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License along
*    with this program; if not, write to the Free Software Foundation, Inc.,
*    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include "ssi_componentparser.h"




//template< class T > list<T>::iterator ssi_list_next( list<T>::iterator curr ){
//   return ++curr;
//}

//template< class T > list<T>::iterator ssi_list_prev( list<T>::iterator curr ){
//   return --curr;
//}

ScriptComponentT::ScriptComponentT(){
}

ScriptComponentT::ScriptComponentT(const ScriptComponentT& Other){
	Component = Other.Component;
	Type = Other.Type;
	Vars = Other.Vars;
}

SSI_BOOL ScriptComponentT::pop(CVariable& Var){
	VarItor PopItor = --Vars.end();
  if(PopItor == Vars.end()) return 0;
	Var = *PopItor;
	Vars.pop_back();
	return 1;
}

ScriptComponentT::~ScriptComponentT(){
}



ComponentItor CComponentParser::next(ComponentItor Curr)
{
	ComponentItor a = m_List.end();
	ComponentItor b = m_List.begin();
	if(Curr == 0) return m_List.end();
	if(Curr == m_List.end()) return m_List.end();
	return ++Curr;
	//return ssi_list_next<ScriptComponentT>(ComponentItor);
}

ComponentItor CComponentParser::prev(ComponentItor Curr)
{
	return --Curr;
	//return ssi_list_prev<ScriptComponentT>(ComponentItor);
}

void CComponentParser::push(ScriptComponentT& New)
{
  m_List.push_back(New);
	//return --Curr;
	//return ssi_list_prev<ScriptComponentT>(ComponentItor);
}



CComponentParser::CComponentParser(void)
{
}

CComponentParser::~CComponentParser(void)
{
}

CStatus CComponentParser::ParseLine(const String& InLine)
{
	String Local = InLine;
	String Component;
	String Token;

	ScriptComponentT C; 
	//String TokenList = "+-*/^(){}=<>!\t ";
  String TokenList = OPERATOR_TOKENS;
  TokenList = TokenList + SSI_CHARS_WHITESPACE;
  TokenList = TokenList + SSI_BRACES;
  TokenList = TokenList + SSI_PARENS;
  //"+-*/^(){}=<>!\t ";

	SSI_INT64 Pos = 0;

	Local.SetQuoteState(1);

	m_List.clear();
	//aTree.Clear();
	while(Local.Parse(TokenList, Component, &Token, 1) >= 0){	
		if(Component.GetLength() > 0){
			C.Component = Component;
			C.Type = COMPONENT_STATEMENT;
			C.Component.SetQuoteState(1);
			m_List.push_back(C);
			//aTree.push(C);
		}
		C.Component = Token;
		C.Type = COMPONENT_TOKEN;
		C.Component.SetQuoteState(1);
		m_List.push_back(C);
		//aTree.push(C);
	}

	if(Local.GetLength() > 0){
		C.Component = Local;
		C.Type = COMPONENT_STATEMENT;
		C.Component.SetQuoteState(1);
    m_List.push_back(C);
		//aTree.push(C);
	}
	return STAT_OK;
}

/*
ComponentNode* CComponentParser::GetNextNode(ComponentNode* In)
{
	if(!In) return SSI_NULL;
	CurrPtr = In->next();
	return CurrPtr;
}
*/

ComponentItor CComponentParser::GetNextNode(ComponentItor In)
{
	if(In == end()) return end();
	In++;
	CurrItor = In;
	return In;
}



ComponentItor CComponentParser::GetTop(void)
{
	return m_List.begin();
	//return aTree.getTop();
}

CStatus CComponentParser::DeleteNodeRange(ComponentItor StartNode, ComponentItor EndNode)
{

	// Consider inputting the PreviousNode and returning it... see if that affects anything

	ComponentItor TempNode = m_List.end();
	
	if(EndNode == end()){
	  m_List.erase(StartNode, EndNode);
	  CurrItor = EndNode;
	}else{
	  CurrItor = next(EndNode);
	  m_List.erase(StartNode, next(EndNode));
	}
	
	//CurrPtr = EndNode->next();
	//if(!aTree.clear_range(StartNode, EndNode)){
	//	// Internal error
	//	return STAT_ERR;
	//}
	
	return STAT_OK;
}

ComponentItor CComponentParser::end()
{
	//m_List.resize(m_List.size());
	//m_List.resize(m_List.size());
	return m_List.end();
}

ComponentItor CComponentParser::begin()
{
	return m_List.begin();
}


CStatus CComponentParser::InsertAfter(ComponentItor Before, ScriptComponentT& New)
{
	// insert inserts *before* Before, however, Before is intended to be before New
	if(Before == m_List.end()){
		//Before = 
		//m_List.push_back(New);
		m_List.push_front(New);  // if before doesnt exist, insert it at the front...
		CurrItor = m_List.begin();  //--(m_List.end());
	}else if(next(Before) == m_List.end()){
		m_List.push_back(New);  // If before is not null, but next is, just push on back
		CurrItor = --(m_List.end());
	}else{
		CurrItor = m_List.insert(next(Before), New);
	}

//	ComponentNode* aNode;
//
//	if(!Before){
//		aNode = aTree.getTop();
//		if(!aNode){
//			CurrPtr = aTree.push(New);
//		}else{
//			CurrPtr = aTree.insert_before(New, aNode);
//		}
//	}else{
//		CurrPtr = aTree.insert_after(New, Before);
//	}
	return STAT_OK;
}

ComponentItor CComponentParser::GetCurrItor(void)
{
	return CurrItor;
}

ComponentItor CComponentParser::SetCurrItor(ComponentItor Itor)
{
	CurrItor = Itor;
	return CurrItor;
	//CurrPtr = Ptr;
	//return CurrPtr;
}

//GET LEFT AND GET RIGHT ARE THE PROBLEMS, STUPID!!!

ComponentItor CComponentParser::GetLeft(ComponentItor In)
{
	ComponentItor Itor = In;
	ComponentItor q = end();
	ScriptComponentT C;
	while((Itor = prev(Itor)) != end()){
		C = *Itor;
		if(C.Type == COMPONENT_TOKEN){
			if(C.Component.IsWhiteSpace()){
			}else{
				return Itor;
			}
		}else{
			return Itor;
		}
	}
  return end();

//	while(aNode){
//		aNode->Get(C);
//		if(C.Type == COMPONENT_TOKEN){
//			if(C.Component.IsWhiteSpace()){
//			}else{
//				return aNode;
//			}
//		}else if(C.Type == COMPONENT_TOKEN){
//			return SSI_NULL;
//		}else{
//			return aNode;
//		}
//		aNode = aNode->prev();
//	}
//	return SSI_NULL;
}


/*
ComponentNode* CComponentParser::GetLeft(ComponentNode* In)
{
	ComponentNode* aNode = In;
	ScriptComponentT C;
	aNode = aNode->prev();
	while(aNode){
		aNode->Get(C);
		if(C.Type == COMPONENT_TOKEN){
			if(C.Component.IsWhiteSpace()){
			}else{
				return aNode;
			}
		}else if(C.Type == COMPONENT_TOKEN){
			return SSI_NULL;
		}else{
			return aNode;
		}
		aNode = aNode->prev();
	}
	return SSI_NULL;
}
*/

ComponentItor CComponentParser::GetRight(ComponentItor In)
{
	ComponentItor Itor = In;
	ScriptComponentT C;
	while((Itor = next(Itor)) != end()){
		C = *Itor;
		if(C.Type == COMPONENT_TOKEN){
			if(C.Component.IsWhiteSpace()){
			}else{
				return Itor;
			}
		}else{
			return Itor;
		}
	}
  return end();


//	ComponentNode* aNode = In;
//	ScriptComponentT C;
//	aNode = aNode->next();
//	while(aNode){
//		aNode->Get(C);
//		if(C.Type == COMPONENT_TOKEN){
//			if(C.Component.IsWhiteSpace()){
//			}else{
//				return aNode;
//			}
//		}else if(C.Type == COMPONENT_TOKEN){
//			return SSI_NULL;
//		}else{
//			return aNode;
//		}
//		aNode = aNode->next();
//	}
//	return SSI_NULL;
}


/*
ComponentNode* CComponentParser::GetRight(ComponentNode* In)
{
	ComponentNode* aNode = In;
	ScriptComponentT C;
	aNode = aNode->next();
	while(aNode){
		aNode->Get(C);
		if(C.Type == COMPONENT_TOKEN){
			if(C.Component.IsWhiteSpace()){
			}else{
				return aNode;
			}
		}else if(C.Type == COMPONENT_TOKEN){
			return SSI_NULL;
		}else{
			return aNode;
		}
		aNode = aNode->next();
	}
	return SSI_NULL;
}
*/




